Repository navigation
Stop creating launch, compile, and KSP tasks at configuration time - #99
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stop the Compiler Gradle plugin from creating the `launch*SpineCompiler`, `compile*Java`, `compile*Kotlin`, and `ksp*Kotlin` tasks by name while the projects are configured (#98). - Register the launch and clean tasks via `sourceSets.configureEach`, which also serves source sets added later, instead of an `afterEvaluate` fallback. - Make the Java, Kotlin, and KSP tasks depend on the launch task via `tasks.named { … }.configureEach`, which also covers tasks registered later. - Let the launch task depend on its `generate*Proto` task by provider. Gradle forbids configuring other tasks from a lazy configuration action, so the `GenerateProtoTask` action no longer touches the launch task. - Add `TaskLocator.exists()` and `named()`, which create no tasks. `generate*Proto` tasks are still configured eagerly: configuring them rewrites the source set directories, which must happen before the Protobuf Gradle Plugin passes them to the IDEA plugin. A lazy action fails that with `ConcurrentModificationException`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec passed with the `protoc` output filter of `compileJava` disabled: - The directory was added to the source set before the evaluation, and the plugin removes it from the source set then, so the task filter had nothing to filter. The directory is now re-added after the evaluation. - The leaked directory was added via the `@TempDir` path, which goes through the `/var` symbolic link on macOS, so the file was reported under a path that differs from the asserted one. The paths now come from `project.projectDir`. The assertions inspect the `files` of the task source, with a positive control for a hand-written file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cover a build that makes Gradle create each task as soon as it is registered, and document the registration order the launch task relies on to find its `generate*Proto` task. - Make `consumeProtoFrom()` private and look the task up with the reified `named<GenerateProtoTask>()`. - Pass the source set first to both helpers of `createTasks()`. - Fix the wording of the KDoc and comments, including the `find()` return description, and document `UnknownTaskException` thrown by `get()`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
🟢 Approved
No active review issues are recorded for the lazy task-wiring changes.
No open issues 🎉
What changed in this PR
Addresses part of #98 by reducing configuration-time task creation in the Compiler Gradle plugin while preserving task dependencies. Protobuf generation tasks intentionally remain eager to avoid the documented IDEA integration failure.
Changes:
- Uses task providers and lazy configuration to connect launch, compilation, KSP, and clean tasks, including late-added tasks and source sets.
- Adds non-realizing
TaskLocatorAPIs and regression tests for task wiring, configuration order, and source filtering. - Advances the compiler version to
2.0.0-SNAPSHOT.082and refreshes dependency reports.
| File | Description |
|---|---|
version.gradle.kts |
Advances the compiler snapshot version. |
gradle-plugin/src/test/kotlin/io/spine/tools/compiler/gradle/plugin/TaskWiringSpec.kt |
Adds lazy task wiring and configuration-order regression tests. |
gradle-plugin/src/test/kotlin/io/spine/tools/compiler/gradle/plugin/ProjectConfigSpec.kt |
Resolves task dependencies to recognize provider-backed edges. |
gradle-plugin/src/test/kotlin/io/spine/tools/compiler/gradle/plugin/ExcludeProtocOutputSpec.kt |
Strengthens source-filter assertions and fixes path handling. |
gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/Plugin.kt |
Registers and wires tasks lazily while retaining eager Protobuf configuration. |
gradle-plugin/src/main/kotlin/io/spine/tools/compiler/gradle/plugin/LaunchSpineCompiler.kt |
Consumes Protobuf task dependencies and source directories through providers. |
gradle-api/src/test/kotlin/io/spine/tools/compiler/gradle/api/TaskLocatorSpec.kt |
Tests non-realizing task lookup and missing-task behavior. |
gradle-api/src/main/kotlin/io/spine/tools/compiler/gradle/api/TaskLocator.kt |
Adds exists() and named() APIs with lifecycle documentation. |
docs/dependencies/pom.xml |
Updates the dependency-report project version. |
docs/dependencies/dependencies.md |
Refreshes report versions and generation timestamps. |
.agents/tasks/lazy-task-wiring.md |
Records the implementation plan and reported verification results. |
Review effort: Balanced
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore ToolBase `2.0.0-SNAPSHOT.430`, which `./config/pull` reverted to `.428`. The Compiler does not call the lazy compile-task API added in `.430`: the CoreJvm Compiler fat JAR on the build-script classpath of consumers bundles an older ToolBase, which would fail such calls with `NoSuchMethodError`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `jar` task of `protoc-plugin` has the `exe` classifier, so its publication has no main artifact, and Gradle has derived the `pom` packaging for its POM. `spinePublishing` now declares the `jar` packaging for standard publications and fails writing a POM whose publication has no main JAR (config#821). Restore the packaging published so far. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move ToolBase and its dogfooding version to `2.0.0-SNAPSHOT.440`, the first version that publishes `jvm-tool-plugins` and `protobuf-setup-plugins` as plain JARs (SpineEventEngine/tool-base#201). `./config/pull` had reverted `version` to `.428`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move CoreJvm Compiler and its dogfooding version to `2.0.0-SNAPSHOT.101`, which no longer bundles ToolBase classes in `core-jvm-plugins` (SpineEventEngine/core-jvm-compiler#125). The ToolBase classes on the build classpath of projects applying `io.spine.core-jvm` now come from the declared ToolBase `.440` artifacts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #99 +/- ##
============================================
+ Coverage 78.27% 79.92% +1.65%
- Complexity 707 709 +2
============================================
Files 207 207
Lines 4648 4632 -16
Branches 407 400 -7
============================================
+ Hits 3638 3702 +64
+ Misses 879 802 -77
+ Partials 131 128 -3 🚀 New features to boost your workflow:
|
Closes #98. The Compiler Gradle plugin no longer creates the
launch*SpineCompiler,compile*Java,compile*Kotlin, andksp*Kotlintasks by name while the projects are configured. Thegenerate*Protocall site stays eager by design; see below.What changed
handleLaunchTaskDependency()→TaskLocator.find()generate*Prototask by provider, from its registration action (LaunchSpineCompiler.setDependencies()).LaunchSpineCompiler.setDependencies()→ tool-basefind*CompileFor()compile*Java,compile*Kotlin, andksp*Kotlindepend on the launch task viatasks.named { … }.configureEach { dependsOn(launchTask) }, right after the launch task is registered. tool-base#198 is not needed.arrangeKspTaskDependency()(afterEvaluate)configureGenerateProtoTasks()sourceSets.configureEach. This replaces the eagerforEachand theafterEvaluatefallback for source sets added later.TaskLocator(public,gradle-api) gainsexists()andnamed(), which do not create the task.find()andget()are unchanged.Why the issue's suggested fix could not be used as is
Gradle (9.8.2) forbids configuring other tasks from inside a lazy task configuration action.
named(…).configure {},configureEach {}, andafterEvaluate {}all fail with "… cannot be executed in the current context". So thegenerateProtoaction cannot wire the launch task lazily. The wiring now goes the other way: the launch task pulls its producer by provider.Why
generate*Protostays eagerWith
generateProtoTasks.all().configureEach {}, thetests/integration build failed withConcurrentModificationException:postConfigureright after thegenerateProtoTasks {}blocks.ideaapplied,postConfigurecallsUtils.addToIdeSources(), which readssourceSets.main.java.srcDirs.generateProtooutput provider, which creates the task.configureSourceSetDirs(), which runssetSrcDirs()on the collection being iterated.That is the "configuration order" the old comment guarded. The comment now says so, and
TaskWiringSpechas a regression test withideaapplied.Keeping this call site eager is accepted as the resolution of #98 for
generate*Proto:generateProtoTask.get()inpostConfigurewheneverideaoreclipseis applied. In such builds these tasks are created during configuration whatever the Compiler does.ProtobufSetupPlugincreates them at the same stage. Making them lazy would first require tool-base to rewrite the source-set directories per source set, outside the task configuration.generateProto,generateTestProto).Measured (
./gradlew help, published.081vs this branch)ksp-testfunctional fixture (real Kotlin + KSP plugins):launch{,Test}SpineCompiler,compile{,Test}Java,compile{,Test}Kotlin,ksp{,Test}Kotlin.generate{,Test}Proto(eager on purpose),process{,Test}Resources(tool-base#198),help,clean.tests/build: the total is unchanged (169 of 219).buildSrc'sDokkaExts.disableDocumentationTasks(config#820).Dependency and
configupdatesLater commits move the build to the releases that came out of the same effort in the other repositories.
config, pulled twice (363fc1da, thenba47b5fb):buildSrchelpers of Configure tasks lazily in thebuildSrchelpers config#821 and the plainjvm-tool-pluginscoordinates of PointToolBase.jvmToolPluginsto the plain plugin JAR config#822..577, Validation.469, Base for build scripts.462, Time.253, BaseTypes.227, Change.209, DokkaTools.12.protoc-pluginPOM: config#821 now declares thejarpackaging for standard publications. Writing the POM fails if the publication has no main JAR.jartask ofprotoc-pluginhas theexeclassifier, so the module sets thepompackaging itself..081and.082POMs have it too..428→.440, bothversionanddogfoodingVersion..440publishesjvm-tool-pluginsandprotobuf-setup-pluginsas plain JARs (Publishprotobuf-setup-pluginsandjvm-tool-pluginsas plain JARs tool-base#201)..099→.101, bothversionanddogfoodingVersion..101no longer bundles ToolBase classes incore-jvm-plugins(Stop bundling ToolBase classes incore-jvm-pluginscore-jvm-compiler#125).io.spine.core-jvm, the fat JAR's ToolBase.428classes shadowed the ToolBase the Compiler plugin declares.tests/build loads them fromplugin-base-2.0.0-SNAPSHOT.440.jar.javaCompileTasksFor()andkotlinCompileTasksFor(), which ToolBase.430added..099or older on the classpath, these calls fail withNoSuchMethodError.For reviewers
dependsOn:TaskProvider<LaunchSpineCompiler>, not the task.TaskProvider<GenerateProtoTask>, not the task.dependsOnforTaskinstances will not see these edges.ProjectConfigSpecnow resolvestaskDependenciesinstead. No Spine sibling repo does such filtering.generate*Prototask by name when Gradle creates it. This relies on protobuf-gradle-plugin being applied first, whichprotobufExtensionOrFail()enforces. That plugin registers the task in its own earliersourceSets.configureEach. A test covers a build that creates each task as soon as it is registered.ExcludeProtocOutputSpec: the spec passed with theprotocfilter disabled./var→/private/varsymlink made the asserted path differ from the reported one.Testing
./gradlew build dokkaGeneratepasses: unit, functional, and integration tests, detekt, and Dokka. It passes again after each dependency update above, the last time with ToolBase.440and CoreJvm Compiler.101.TaskWiringSpec(12 cases) verifies that the dependencies hold and that the tasks are not created at configuration time.ideacase fails against theconfigureEachvariant.TaskLocatorSpechas 3 new cases.🤖 Generated with Claude Code